//
//  History.m
//  iMed
//
//  Created by Barry Press on 10/9/09.
//  Copyright 2009 Barry Press. All rights reserved.
//

#import "History.h"
#import "DataSet.h"
#import "MyDocument.h"
#include "TimeIntervalFormatter.h"


@implementation History

#pragma mark Standard init / destroy / coder
// ---------------------------------------------- copyWithZone -----------------
- (id)copyWithZone:(NSZone *)zone
{
	History* h = [[History allocWithZone:zone] init];
	// 
	// The notion here is that the RX, Timestamp, and PriorRX
	// should not be edited via a history item directly - if they
	// do change, then either it's a change to all referencing
	// objects, or else the referencing object that's changing 
	// should make a new object for them at the time of the change.
	//
	[h setRx:[self rx]];
	[h setRxcount:[self rxcount]];
	[h setDose:[self dose]];
	[h setTimestamp:[self timestamp]];
	[h setPriorrx:[self priorrx]];
	[h setInterval:[self interval]];
	[h setRunninginterval:[self runninginterval]];
	return h;
}

#pragma mark description
// ---------------------------------------------- description ------------------
- (NSString*)description
{
	return [NSString stringWithFormat:@"NDC %@, Time %@, Int %.2f %@ R-Int %.2f %@",
			self.rx.ndc.name,
			[self timestamp], 
			[self interval], 
			[TimeIntervalFormatter makeFormattedStringFromInterval:interval],
			[self runninginterval],
			[TimeIntervalFormatter makeFormattedStringFromInterval:runninginterval]];
}

#pragma mark Archiving methods
// =============================================================================
// ---------------------------------------------- dealloc ----------------------
- (void)dealloc
{
	[rx release];
	rx = NULL;
	[timestamp release];
	timestamp = NULL;
	[priorrx release];
	priorrx = NULL;
	[super dealloc];
}

// ---------------------------------------------- encodeWithCoder --------------
- (void)encodeWithCoder:(NSCoder *)coder
{
	NSAssert(rx != NULL, @"NULL rx pointer in History:encodeWithCoder");
	NSAssert(timestamp != NULL, @"NULL timestamp pointer in History:encodeWithCoder");
	NSAssert(priorrx != NULL, @"NULL priorrx pointer in History:encodeWithCoder");

	[coder encodeObject:rx forKey:@"Hrx"];
	[coder encodeFloat:rxcount forKey:@"Hrxcount"];
	[coder encodeFloat:dose forKey:@"Hdose"];
	[coder encodeObject:timestamp forKey:@"Htimestamp"];
	[coder encodeObject:priorrx forKey:@"Hpriorrx"];
	[coder encodeFloat:interval forKey:@"Hinterval"];
	[coder encodeFloat:runninginterval forKey:@"HrunningInterval"];
}
					
// ---------------------------------------------- initWithCoder ----------------
- (id)initWithCoder:(NSCoder *)coder
{
	[super init];
	rx =				[[coder decodeObjectForKey:@"Hrx"] retain];
	rxcount =			 [coder decodeFloatForKey:@"Hrxcount"];
	dose =				 [coder decodeFloatForKey:@"Hdose"];
	timestamp =			[[coder decodeObjectForKey:@"Htimestamp"] retain];
	priorrx =			[[coder decodeObjectForKey:@"Hpriorrx"] retain];
	interval =			 [coder decodeFloatForKey:@"Hinterval"];
	runninginterval =	 [coder decodeFloatForKey:@"HrunningInterval"];
	return self;
}

// ---------------------------------------------- init -------------------------
- (id)init
{
	[super init];
	rx = nil;
	rxcount = 0.0;
	dose = 1.0;
	timestamp = nil;
	priorrx = nil;
	interval = 0.0;
	runninginterval = 0.0;
	return self;
}

// ---------------------------------------------- initWithRX:withDose:Count:atTime:
- (id)initWithRX:(RX*)arx withDose:(float)adose Count:(float)acount 
		  atTime:(NSDate*)adate
{
	return [self initWithRX:arx 
				   withDose:adose 
					  Count:acount 
					 atTime:adate 
	  returningPriorHistory:NULL];
}

- (id)initWithRX:(RX*)arx withDose:(float)adose Count:(float)acount 
		  atTime:(NSDate*)adate returningPriorHistory:(History**)priorHistory
{
	DataSet* dataset = CURRENTDATASET;
	History* prior = [[dataset history] priorRXHistory:arx];
	[self init];
	if (priorHistory != NULL) {
		*priorHistory = prior;
	}
	if (prior && [[prior timestamp] isGreaterThan:adate]) {
		NSRunAlertPanel(@"Date Error", 
						@"Date precedes history entry for this RX", 
						@"OK", 
						NULL, NULL);
		[self autorelease];
		return nil;
	}
	[self setRx:arx];
	[self setDose:adose];
	[self setRxcount:acount];
	[self setTimestamp:adate];
	[self setPriorrx:[prior timestamp]];
	if ([self priorrx] == nil) {
		[self setPriorrx:[self timestamp]];
	}
	[self setInterval:[[self timestamp] timeIntervalSinceDate:[self priorrx]]];
	return self;
}

#pragma mark predicates
// =============================================================================
// ---------------------------------------------- isForRX ----------------------
- (BOOL)isForRX:(RX*)aRX
{
	return ([self rx] == aRX);
}

#pragma mark Accessor methods

// ---------------------------------------------- accessors --------------------
@synthesize rx;
@synthesize rxcount;
@synthesize dose;
@synthesize timestamp;
@synthesize interval;
@synthesize runninginterval;
@synthesize priorrx;

@end
